package com.b.server.config;
 
import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.redis.RedisDataSource;
import com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
 
import java.util.List;
 
 
/**
 * @author zhuhongqiang3
 * @package: com.example.sentinel_demo.config
 * @title: RedisDataSourceConfig
 * @projectName: sentinel_demo
 * @description: //TODO
 * @date: 2020-05-18 10:36
 * @version: V1.0
 * @retrun com.example.sentinel_demo.config.sentinel_demo
 */
@Component
public class RedisDataSourceConfig implements ApplicationRunner {
    private static final Logger log = LoggerFactory.getLogger(RedisDataSourceConfig.class);
 
    @Value("${spring.redis.host}")
    public String redisHost;
 
    @Value("${spring.redis.port}")
    public int redisPort;
 
    @Value("${spring.redis.password}")
    public String redisPass;
 
    //限流规则key前缀
    public final String RULE_FLOW = "sentinel_rule_flow_";
    public final String RULE_FLOW_CHANNEL = "sentinel_rule_flow_channel";
 
    //降级规则key前缀
    public final String RULE_DEGRADE = "sentinel_rule_degrade_";
    public final String RULE_DEGRADE_CHANNEL = "sentinel_rule_degrade_channel";
 
    //系统规则key前缀
    public final String RULE_SYSTEM = "sentinel_rule_system_";
    public final String RULE_SYSTEM_CHANNEL = "sentinel_rule_system_channel";
 
    /**
     * ApplicationRunner
     * 该接口的方法会在服务启动之后被立即执行
     * 主要用来做一些初始化的工作
     * 但是该方法的运行是在SpringApplication.run(…​) 执行完毕之前执行
     */
    @Override
    public void run(ApplicationArguments args) {
        log.info(">>>>>>>>>执行sentinel规则初始化 start。。。");
        RedisConnectionConfig config = RedisConnectionConfig.builder().withHost(redisHost).withPort(redisPort).withPassword(redisPass).build();
 
        Converter<String, List<FlowRule>> parser = source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
        });
        String ruleAppName = RULE_FLOW + SentinelConfig.getAppName();
        log.info("ruleAppName>>>" + ruleAppName);
        ReadableDataSource<String, List<FlowRule>> redisDataSourceFlow = new RedisDataSource<>(config, ruleAppName, RULE_FLOW_CHANNEL, parser);
        FlowRuleManager.register2Property(redisDataSourceFlow.getProperty());
 
        Converter<String, List<DegradeRule>> parserDegrade = source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
        });
        ReadableDataSource<String, List<DegradeRule>> redisDataSourceDegrade = new RedisDataSource<>(config, RULE_DEGRADE + SentinelConfig.getAppName(), RULE_DEGRADE_CHANNEL, parserDegrade);
        DegradeRuleManager.register2Property(redisDataSourceDegrade.getProperty());
 
        Converter<String, List<SystemRule>> parserSystem = source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>() {
        });
        ReadableDataSource<String, List<SystemRule>> redisDataSourceSystem = new RedisDataSource<>(config, RULE_SYSTEM + SentinelConfig.getAppName(), RULE_SYSTEM_CHANNEL, parserSystem);
        SystemRuleManager.register2Property(redisDataSourceSystem.getProperty());
        log.info(">>>>>>>>>执行sentinel规则初始化 end。。。");
    }
}